package com.yikome.storehouse.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.yikome.common.CommonService;
import com.yikome.storehouse.dto.InventoryDTO;
import com.yikome.storehouse.dto.RemoteClearStorehouseCheckRequest;
import com.yikome.storehouse.dto.StorehouseTreeGrid;
import com.yikome.storehouse.entity.Inventory;
import com.yikome.storehouse.entity.Storehouse;
import com.yikome.storehouse.repository.InventoryRepository;
import com.yikome.storehouse.repository.StorehouseRepository;
import com.yikome.storehouse.request.InventoryEditRequest;
import com.yikome.storehouse.request.InventoryRequest;
import com.yikome.utils.BeanUtils;
import com.yikome.utils.NamedParameterJdbcUtils;
import com.yikome.utils.SecurityUtils;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;

import cn.hutool.core.util.StrUtil;

@Service
public class StorehouseService extends CommonService<Storehouse, Long> {

	@Autowired
	private StorehouseRepository storehouseRepository ; 
	
	@Autowired
	private InventoryRepository inventoryRepository ; 
	
	@Autowired
	private NamedParameterJdbcTemplate jdbcTemplate ;

	public List<StorehouseTreeGrid> findStorehouseTreeGrid() {
		
		List<Storehouse> storehouses = new ArrayList<>();
		
		List<String> roles = SecurityUtils.getCurrentRoles();
		if(roles.size() == 1 && roles.contains("storehouse")) {
			storehouses = storehouseRepository.findManagerStorehouse(StrUtil.wrap(SecurityUtils.getCurrentUsername(), "%"));
		}else {
			storehouses = storehouseRepository.findStorehouse();
		}
		
		List<StorehouseTreeGrid> storehouseTreeGrids = new ArrayList<>();
		for (Storehouse storehouse : storehouses) {
			if(storehouse.getPrimarryStorehouseId() == null) {
				StorehouseTreeGrid storehouseTreeGrid = new StorehouseTreeGrid();
				BeanUtils.copyProperties(storehouse, storehouseTreeGrid);
				storehouseTreeGrid.setStorehouseId(storehouse.getId());
				
				List<StorehouseTreeGrid> children = findStorehouseChild(storehouses , storehouse.getId()) ; 
				if(children != null && !children.isEmpty())storehouseTreeGrid.setChildren(children);
				
				storehouseTreeGrids.add(storehouseTreeGrid);
			}
		}
		return storehouseTreeGrids;
	}

	private List<StorehouseTreeGrid> findStorehouseChild(List<Storehouse> storehouses, Long storehouseId) {
		
		List<StorehouseTreeGrid> children = new ArrayList<>();
		
		for (Storehouse storehouse : storehouses) {
			if(storehouseId.equals(storehouse.getPrimarryStorehouseId())) {
				
				StorehouseTreeGrid storehouseTreeGrid = new StorehouseTreeGrid();
				BeanUtils.copyProperties(storehouse, storehouseTreeGrid);
				storehouseTreeGrid.setStorehouseId(storehouse.getId());
				
				children.add(storehouseTreeGrid);
			}
		}
		
		return children.isEmpty() ? null : children;
	}

	public List<Map<String, Object>> findStorehouseCombo() {
		
		List<String> roles = SecurityUtils.getCurrentRoles();
		if(roles.contains("storehouse")) {
			
			String contentSQL = "SELECT '' AS 'id', '所有仓库' AS 'text' \n" + 
								"UNION \n" + 
								"SELECT s_storehouse.id , s_storehouse.storehouse_name FROM s_storehouse WHERE s_storehouse.yn = 1 AND s_storehouse.managers LIKE :username AND s_storehouse.primarry_storehouse_id IS NULL \n" ;
			return jdbcTemplate.queryForList(contentSQL, ImmutableMap.of("username" , StrUtil.wrap(SecurityUtils.getCurrentUsername(), "%")));
			
		}
		
		String contentSQL = "SELECT '' AS 'id', '所有仓库' AS 'text' \n" + 
							"UNION \n" + 
							"SELECT s_storehouse.id , s_storehouse.storehouse_name FROM s_storehouse WHERE s_storehouse.yn = 1 AND s_storehouse.primarry_storehouse_id IS NULL \n" ;
		return jdbcTemplate.queryForList(contentSQL, ImmutableMap.of());
	}

	@Transactional
	public void deleteStorehouseId(Long storehouseId) {
		
		Storehouse storehouse = storehouseRepository.findStorehouse(storehouseId);
		
		Preconditions.checkArgument(storehouse != null, "数据信息不存在");
		
		storehouse.setYn(0);
		storehouseRepository.save(storehouse);
		
	}

	
	public Page<InventoryDTO> findInventoryDTO(InventoryRequest inventoryRequest, Pageable pageable) {
		
		String contenSQL =  "SELECT \n" + 
							" 	s_inventory.id inventory_id, s_inventory.product_name, s_inventory.product_sku_barcode, s_inventory.product_sku_name, s_inventory.product_sku_image, s_inventory.inventory, s_inventory.comments, s_storehouse.storehouse_name \n" + 
							"FROM s_inventory \n" + 
							"	LEFT JOIN s_storehouse ON (s_inventory.storehouse_id = s_storehouse.id) \n" ; 
		
		StringBuilder paramsSQL = new StringBuilder("WHERE s_inventory.yn = 1 \n");
		Map<String , Object> paramsMap = new HashMap<>();
		
		if(inventoryRequest.getStorehouseId() != null) {
			paramsSQL.append("AND s_inventory.storehouse_id = :storehouseId \n");
			paramsMap.put("storehouseId", inventoryRequest.getStorehouseId());
		}
		if(StrUtil.isNotBlank(inventoryRequest.getProductSkuBarcode())) {
			paramsSQL.append("AND s_inventory.product_sku_barcode = :productSkuBarcode \n");
			paramsMap.put("productSkuBarcode", inventoryRequest.getProductSkuBarcode());
		}
		
		String orderSQL = NamedParameterJdbcUtils.findOrderSQL(pageable);
		String pageSQL = NamedParameterJdbcUtils.findPageSQL(pageable);
		
		List<InventoryDTO> inventoryDTOs = jdbcTemplate.query(contenSQL + paramsSQL + orderSQL + pageSQL, paramsMap, new BeanPropertyRowMapper<>(InventoryDTO.class));
		
		Long total = jdbcTemplate.queryForObject("SELECT COUNT(1) FROM (" + contenSQL + paramsSQL + ") T", paramsMap, Long.class);
		
		return new PageImpl<>(inventoryDTOs, pageable, total);
	}

	@Transactional
	public Inventory editInventory(InventoryEditRequest inventoryEditRequest) {

		Inventory inventory = inventoryRepository.findInventory(inventoryEditRequest.getStorehouseId(), inventoryEditRequest.getProductSkuBarcode());
		
		Preconditions.checkArgument(inventory != null, "商品库存不存在...");
		
		inventory.setInventory(inventoryEditRequest.getQuantity());
		if(StrUtil.isNotBlank(inventoryEditRequest.getComments()))inventory.setComments(inventoryEditRequest.getComments());
		return inventoryRepository.save(inventory);
	}

	@Transactional
	public void remoteCheck(RemoteClearStorehouseCheckRequest remoteClearStorehouseCheckRequest) {
		
		Inventory inventory = inventoryRepository.findInventory(remoteClearStorehouseCheckRequest.getStorehouseId(), remoteClearStorehouseCheckRequest.getProductSkuBarcode());
		if(inventory == null) {
			List<Inventory> inventories = inventoryRepository.findInventory(remoteClearStorehouseCheckRequest.getProductSkuBarcode());
			Preconditions.checkArgument(inventories != null && !inventories.isEmpty(), "商品不存在...");
			
			inventory = new Inventory();
			inventory.setProductName(inventories.get(0).getProductName());
			inventory.setProductSkuBarcode(remoteClearStorehouseCheckRequest.getProductSkuBarcode());
			inventory.setProductSkuName(inventories.get(0).getProductSkuName());
			inventory.setProductSkuImage(inventories.get(0).getProductSkuImage());
			inventory.setInventory(0);
			inventory.setStorehouseId(remoteClearStorehouseCheckRequest.getStorehouseId());
			inventory.setComments("远程盘点导入");
		}
		
		Preconditions.checkArgument(inventory != null, "商品不存在...");
		
		inventory.setInventory(inventory.getInventory() + remoteClearStorehouseCheckRequest.getQuantity());
		inventoryRepository.save(inventory);
	}
}
